home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir37 / ms_sh23s.zip / SRC / SWAP.ASM < prev    next >
Assembly Source File  |  1994-08-26  |  23KB  |  1,356 lines

  1.     TITLE   swap.asm
  2.     NAME    swap
  3.     .8087
  4.  
  5. ; MS-DOS System Function with Swaping - Front End
  6. ;
  7. ; MS-DOS System - Copyright (c) 1990,1,2 Data Logic Limited
  8. ;
  9. ; This code is subject to the following copyright restrictions:
  10. ;
  11. ; 1.  Redistribution and use in source and binary forms are permitted
  12. ;     provided that the above copyright notice is duplicated in the
  13. ;     source form.
  14. ;
  15. ;    $Header: /usr/users/istewart/shell/sh2.3/Release/RCS/swap.asm,v 2.0 1992/05/21 16:49:54 Ian_Stewartson Exp $
  16. ;
  17. ;    $Log: swap.asm,v $
  18. ;    Revision 2.0  1992/05/21  16:49:54  Ian_Stewartson
  19. ;    MS-Shell 2.0 Baseline release
  20. ;
  21. ;    Revision 2.0  1992/04/13  17:39:45  Ian_Stewartson
  22. ;    MS-Shell 2.0 Baseline release
  23. ;
  24. ;
  25. ; MODULE DEFINITION:
  26. ;
  27. ; This is the front end for the swapping version of system.  When linked
  28. ; in, it should be the first module in the load line so that it appears in
  29. ; memory immediately after the psp.  For example:
  30. ;
  31. ;   link swap+x1+x2+x3+system;
  32. ;
  33. ; This module has no user changeable features.  All selections are
  34. ; performed in the associated system function.
  35. ;
  36. ; If you want small model, you can only get small model data.  This
  37. ; requires this module to be compiled with the -DSMALL_DATA switch to the
  38. ; assembler.
  39. ;
  40. ; More details in system.c
  41. ;
  42. ; Author:
  43. ;    Ian Stewartson
  44. ;    Data Logic, Queens House, Greenhill Way
  45. ;    Harrow, Middlesex  HA1 1YR, UK.
  46. ;    istewart@datlog.co.uk or ukc!datlog!istewart
  47. ;
  48. ;
  49.  
  50. ;
  51. ; Segment declarations
  52. ;
  53.  
  54. SWAP_TEXT    segment word public 'CODE'
  55. SWAP_TEXT    ends
  56.  
  57. _DATA        segment word public 'DATA'
  58. _DATA        ends
  59.  
  60. CONST        segment word public 'CONST'
  61. CONST        ends
  62.  
  63. _BSS        segment word public 'BSS'
  64. _BSS        ends
  65.  
  66. DGROUP        group    CONST, _BSS, _DATA
  67.  
  68. ;
  69. ; Declare external functions and data
  70. ;
  71.     extrn    __maperror:far
  72.     extrn    _errno:word
  73.     extrn    __psp:word
  74.  
  75. ;
  76. ; Start of the spawn function
  77. ;
  78.  
  79. SWAP_TEXT    segment
  80.         assume  cs: SWAP_TEXT, ds: NOTHING, ss: DGROUP
  81.  
  82. ;
  83. ; For this function, all the code and data space are in the code space
  84. ;
  85.         public    _cmd_line
  86.         public    _path_line
  87.         public    _SW_intr
  88.         public    _SW_Blocks
  89.         public    _SW_fp
  90.         public    _SW_EMstart
  91.         public    _SW_Mode
  92.         public    _SW_EMSFrame
  93.         public    _SW_Int00
  94.         public    _SW_Int23
  95.         public    _SW_XMS_Driver
  96.         public    _SW_XMS_Gversion
  97.         public    _SW_XMS_Allocate
  98.         public    _SW_XMS_Free
  99.         public    _SW_XMS_Available
  100.         public    _SW_I23_InShell
  101.  
  102.  
  103. _cmd_line    db    129 dup (?)    ; Command line
  104. _path_line    db    80 dup (?)    ; Path line
  105. _SW_Blocks    dw    0        ; Number of blocks to read/write
  106. _SW_fp        dw    0ffffH        ; File ID
  107. _SW_EMstart    dd    0100000H    ; Default Extended Mem start
  108. _SW_Mode    dw    0        ; Type of swapping to do
  109.                     ;   1 - disk
  110.                     ;   2 - Extended memory
  111.                     ;   3 - EMS driver
  112.                     ;   4 - XMS driver
  113. _SW_EMSFrame    dw    0        ; EMS Frame segment
  114. _SW_intr    dw    0        ; Interrupt 23 detected.
  115. _SW_XMS_Driver    dd    0        ; XMS Driver Interface
  116. _SW_I23_InShell    db    0        ; In shell flag for Interrupt 23
  117.  
  118.  
  119. ;
  120. ; Some addition variables
  121. ;
  122.  
  123. SW_LMstart    dd    0        ; Low Mem start for Extended Mem swap
  124. N_mcb        dw    0        ; Start write address
  125. Result        dw    0        ; Return value
  126.  
  127. ;
  128. ; Stack save pointers
  129. ;
  130.  
  131. S_ss        dw    0            ; Save Stack pointers
  132. S_sp        dw    0
  133. S_di        dw    0            ; Save DI, SI
  134. S_si        dw    0
  135. S_ds        dw    0            ; Save the original DS
  136.  
  137. ;
  138. ; Two blank FCB
  139. ;
  140.  
  141. FCB1        dw    16    dup (?)
  142. FCB2        dw    16    dup (?)
  143.  
  144. ;
  145. ; XMS Driver Move structure
  146. ;
  147.  
  148. XMS_DIF        equ    $
  149. XMS_Length    dd    0            ; Number of bytes
  150. XMS_SHandle    dw    0            ; Source Handler
  151. XMS_Soffset    dd    0            ; Source Offset
  152. XMS_DHandle    dw    0            ; Destination Handler
  153. XMS_Doffset    dd    0            ; Destination Offset
  154.  
  155. ;
  156. ; Extended Memory Global Descriptor tables
  157. ;
  158.         org    XMS_DIF
  159. GD_table    equ    $
  160. GDT_Dummy    dw    4    dup (0)        ; Dummy
  161. GDT_self    dw    4    dup (0)        ; For self
  162. GDT_src        equ    $            ; Source
  163.         dw    04000H            ; Length - 16K bytes
  164. GDT_src_low    dw    0            ;     Low Order address
  165. GDT_src_high    db    0            ;     High Order address
  166.         db    093h            ;     Access Rights
  167.         dw    0            ;     Reserved
  168. GDT_dest    equ    $            ; Destination
  169.         dw    04000H            ;     Length - 16K bytes
  170. GDT_dest_low    dw    0            ;     Low Order address
  171. GDT_dest_high    db    0            ;     High Order address
  172.         db    093h            ;     Access Rights
  173.         dw    0            ;     Reserved
  174. GDT_bios    dw    4    dup (0)        ; Bios
  175. GDT_stack    dw    4    dup (0)        ; Stack
  176.  
  177. ;
  178. ; Execute interrupt structure
  179. ;
  180.  
  181. exec_parms    equ    $
  182. exec_env    dw    0
  183.         dw    offset _cmd_line    ; Command line address
  184. exec_cseg    dw    ?
  185.         dw    offset FCB1        ; FCB1 address
  186. exec_f1seg    dw    ?
  187.         dw    offset FCB2        ; FCB1 address
  188. exec_f2seg    dw    ?
  189.  
  190. Swap_PANIC    db    'PANIC: Swap file re-load error - REBOOT', 0aH, 0dH
  191.         db    '$'
  192.  
  193. Swap_DZERO    db    'PANIC: Divide by zero', 0aH, 0dH
  194.         db    '$'
  195.  
  196. ;
  197. ; OK - exec requires a local stack, cause some programs overwrite it
  198. ;
  199.         even
  200.         db    398 dup (0)
  201. Local_Stack:
  202.         dw    0
  203.  
  204. ;
  205. ; Code starts
  206. ;
  207.     public    _SA_spawn
  208.  
  209. SA_spawn1    proc    far
  210.     mov    ds, word ptr cs:exec_env    ; Load Env seg.
  211.     xor    si, si                ; Clear start offset
  212.  
  213. ;
  214. ; Copy into Env Seg
  215. ;
  216.  
  217. $Copy_Env:
  218. ifndef SMALL_DATA
  219.     les    bx, dword ptr ss:[bp + 6]    ; Check for end of loop
  220.     mov    ax, word ptr es:[bx + 0]
  221.     or    ax, word ptr es:[bx + 2]
  222. else
  223.     mov    dx, word ptr cs:S_ds        ; Get original DS
  224.     mov    es, dx                ; and dump it in dx for later
  225.     mov    bx, word ptr ss:[bp + 6]    ; Check for end of loop
  226.     mov    ax, word ptr es:[bx + 0]
  227.     or    ax, ax
  228. endif
  229.     je    $Copy_End
  230.  
  231. ;
  232. ; Save start address
  233. ;
  234. ; For small data model,the DX register contains the original DS
  235. ;
  236.  
  237. ifndef SMALL_DATA
  238.     add    word ptr ss:[bp + 6], 4        ; Increment environment by 4
  239.  
  240.     mov    cx, word ptr es:[bx + 0]    ; Load address of cur Env string
  241.     mov    ax, word ptr es:[bx + 2]    ; into es:bx
  242. else
  243.     add    word ptr ss:[bp + 6], 2        ; Increment environment by 2
  244.  
  245.     mov    cx, word ptr es:[bx + 0]    ; Load address of cur Env string
  246.     mov    ax, dx                ; into es:bx
  247. endif
  248.     mov    es, ax
  249.     mov    bx, cx
  250.  
  251. ;
  252. ; Copy this value
  253. ;
  254.  
  255. $Copy_Val:
  256.     mov    al, byte ptr es:[bx]    ; Copy across
  257.     mov    byte ptr ds:[si], al
  258.     inc    bx            ; Increment pointers
  259.     inc    si
  260.     or    al, al
  261.     jne    $Copy_Val
  262.     jmp    $Copy_Env
  263.  
  264. ;
  265. ; Set up exec parameter block     - DS is on stack
  266. ;
  267. $Copy_End:
  268.     xor    ax, ax
  269.     mov    word ptr ds:[si], ax    ; Terminate environment
  270.     add    si, 2
  271.  
  272. ;
  273. ; Set up new program length
  274. ;
  275.     add    si, 16            ; Round up paras
  276.     mov    dx, si            ; Save end offset in DX
  277.     mov    bx, ds
  278.  
  279.     mov    cl, 4
  280.     shr    si, cl            ; # paras used by Env
  281.     add    si, bx            ; End para number
  282.  
  283.     mov    bx, word ptr cs:N_mcb    ; Load our MCB address in BX
  284.     mov    ax, bx
  285.     inc    ax
  286.     sub    si, ax
  287.     mov    cx, si            ; Save new max paras in CX
  288.  
  289. ;
  290. ; Use interrupt 4a to shrink memory.  First release all memory above us.
  291. ;
  292.     push    ax
  293.     push    cx            ; Save Max paras and location
  294.     mov    ds, bx            ; Set up the segement for MCB
  295.     mov    cx, word ptr ds:3    ; Get the MCB length
  296.  
  297. ; Are we the only one in the chain?
  298.  
  299.     cmp    byte ptr ds:0, 'Z'    ; End of chain ?
  300.     jz    $Shrink_First
  301.  
  302. ;
  303. ; Loop round releasing memory blocks
  304. ;
  305. ;    CX - original length of block;
  306. ;    DS - segement of the previous block
  307. ;
  308. $Shrink_Next:
  309.     mov    ax, ds            ; Move to the next block
  310.     add    cx, ax
  311.     inc    cx
  312.     mov    ds, cx
  313.  
  314.     cmp    byte ptr ds:0, 'Z'    ; End of chain ?
  315.     jz    $Shrink_First
  316.  
  317.     mov    cx, word ptr ds:3    ; Save the length of this block
  318.  
  319.     mov    ax, ds            ; Advance to the block itself
  320.     inc    ax
  321.     mov    es, ax            ; Set up Block address
  322.  
  323.     mov    ah, 049H
  324.     int    021H
  325.     jmp    $Shrink_Next
  326.  
  327. ;
  328. ;    Shrink the PSP segment
  329. ;
  330.  
  331. $Shrink_First:
  332.     pop    cx
  333.     pop    ax
  334.         mov    es, ax            ; Set PSP address
  335.     mov    bx, cx            ; Set max length
  336.     mov    ah, 04aH
  337.     int    021H
  338.  
  339. ;
  340. ; Execute function
  341. ;
  342.  
  343.     mov    word ptr cs: S_sp, sp    ; Save the current stack
  344.     mov    word ptr cs: S_ss, ss
  345.  
  346. ;
  347. ; Move to the local stack so that it doesn't get overwritten.
  348. ;
  349.     mov    ax, cs
  350.     cli
  351.     mov    sp, offset Local_Stack
  352.     mov    ss, ax
  353.     sti
  354.  
  355. ; Clear out Interrupts
  356.  
  357.     mov    ah, 00bH        ; Check Keyboard status
  358.     int    021H
  359.  
  360. ;
  361. ;  Check for interrupt 23 detected
  362. ;
  363.     mov    ax, word ptr cs:_SW_intr
  364.     or    ax, ax
  365.     jz    $I23_Cf            ; No - continue;
  366.  
  367. ;
  368. ; Interrupt 23 detected - abort
  369. ;
  370.     mov    ax, cs            ; Set up for reload
  371.     cli
  372.     mov    sp, offset Local_Stack
  373.     mov    ss, ax
  374.     sti
  375.  
  376.     mov    ds, word ptr cs:S_ds    ; Restore DS
  377.     xor    ax, ax
  378.     jmp    $Exec_Complete
  379.  
  380. ;
  381. ; No interrupts - continue
  382. ;
  383. $I23_Cf:
  384.     mov    ax, cs            ; Set up segments
  385.     mov    es, ax
  386.     mov    ds, ax
  387.  
  388.     mov    ax, 04b00H        ; Load and execute function
  389.     mov    dx, offset _path_line    ; Load path
  390.     mov    bx, offset exec_parms    ; Load the execute structure
  391.     mov    byte ptr cs:_SW_I23_InShell, 1    ; Set not shell flag
  392.     int    021H
  393.     mov    byte ptr cs:_SW_I23_InShell, 0    ; Set in shell flag
  394.  
  395. ; Disable interrupts while we restore the stack to the local one
  396.  
  397.     mov    ax, cs
  398.     cli
  399.     mov    sp, offset Local_Stack
  400.     mov    ss, ax
  401.     sti
  402.  
  403. ;
  404. ; Did an error occur?
  405. ;
  406.     jnc    $Exec_OK
  407.  
  408. ;
  409. ; Error
  410. ;
  411.  
  412. $Map_error:
  413.     mov    ds, word ptr cs:S_ds    ; Restore DS
  414.     mov    ah, al
  415.     call    far ptr __maperror    ; Map the error
  416.  
  417. $Exec_Error:
  418.     mov    ax, 0FFFFH
  419.     jmp    $Exec_Complete
  420.  
  421. ;
  422. ; No - get the exit code and check for interrupts
  423. ;
  424.  
  425. $Exec_OK:
  426.     mov    ax, 04d00H
  427.     int    021H
  428.     dec    ah            ; Interrupt termination ?
  429.     jnz    $Exec_OK1
  430.  
  431.     inc    word ptr ds:_SW_intr    ; Set Interrupt 23 detected.
  432.  
  433. $Exec_OK1:
  434.     xor    ah, ah
  435.  
  436. ;
  437. ; Save the result code
  438. ;
  439.  
  440. $Exec_Complete:
  441.     mov    word ptr cs:Result, ax        ; Save response
  442.  
  443. ;
  444. ; Very Dangerous - Restore Environment
  445. ;
  446. ;     Seek to 0x4000 in file
  447. ;
  448.     mov    bx, word ptr cs:_SW_fp        ; Load File Handler
  449.     mov    ax, word ptr cs: _SW_Mode    ; Skip if not disk
  450.     dec    ax
  451.     jnz    $Seek_OK
  452.  
  453. ; Seek in file to skip 16K
  454.  
  455.     mov    dx, 04000H
  456.     call    $Seek_Disk
  457.  
  458. ;
  459. ;     Load from N_mcb:0x4000 to end of file.
  460. ;
  461.  
  462. $Seek_OK:
  463.     mov    si, word ptr cs:_SW_Blocks    ; Load number of transfers
  464.     dec    si                ; Skip first block
  465.  
  466. ;
  467. ; set up ES register with start of load
  468. ;
  469.     mov    ax, word ptr cs:N_mcb    ; Load the start address
  470.     add    ax, 0400H
  471.     mov    ds, ax
  472.  
  473. ; load up extended memory GDT for destination
  474.  
  475.     call    $GDT_reload
  476.     call    $Inc_Extend            ; Increment addresses by 16K
  477.  
  478. ;
  479. ; Check for end of copy    - BX - File Handler for disk
  480. ;
  481.  
  482. $Read_loop:
  483.     or    si, si
  484.     je    $Read_Complete
  485.  
  486. ; OK - Copy next 0x4000 bytes - switch on device
  487.  
  488.     mov    ax, word ptr cs: _SW_Mode
  489.     dec    ax
  490.     jz    $R_disk
  491.     dec    ax
  492.     jz    $R_extend
  493.     dec    ax
  494.     jz    $R_expand
  495.  
  496. ;
  497. ; Read from XMS driver.  In this case, we do one read and let the driver
  498. ; sort out the blocking
  499. ;
  500.     call    $Read_XMS
  501.     jmp     $Read_Complete
  502.  
  503. ; Read from disk
  504.  
  505. $R_disk:
  506.     call    $Read_disk
  507.     jmp    $Read_loop
  508.  
  509. ; Read from extended memory
  510.  
  511. $R_extend:
  512.     call    $Read_extend
  513.     jmp    $Read_loop
  514.  
  515. ; Read from expanded memory
  516.  
  517. $R_expand:
  518.     call    $Read_EMS
  519.     jmp    $Read_loop
  520.  
  521. ;
  522. ; Re-load is now complete, Restore original stack which has just been
  523. ; reloaded.  BX contains FP
  524. ;
  525.  
  526. $Read_Complete:
  527.     cli
  528.     mov    sp, word ptr cs: S_sp        ; Save the current stack
  529.     mov    ss, word ptr cs: S_ss
  530.     sti
  531.  
  532. ;  Save exit code
  533.  
  534.     push    word ptr cs:Result        ; Save response
  535.     push    word ptr cs:_SW_intr        ; and interrupt flag
  536.  
  537. ;
  538. ; Read in the first block - BX - File Handler
  539. ;
  540.  
  541.     mov    ax, word ptr cs: _SW_Mode    ; Skip if not disk
  542.     dec    ax
  543.     jnz    $Seek1_OK
  544.  
  545. ; Seek to 0 in file
  546.  
  547.     xor    dx, dx
  548.     call    $Seek_Disk
  549.  
  550. ;
  551. ;     Load one block at N_mcb:0x0000
  552. ;
  553. $Seek1_OK:
  554.     mov    ds, word ptr cs:N_mcb        ; Load the start address
  555.     call    $GDT_reload            ; Load the GDT for extend mem
  556.  
  557.     mov    ax, word ptr cs: _SW_Mode    ; Skip if not disk
  558.     dec    ax
  559.     jz    $R1_Disk
  560.     dec    ax
  561.     jz    $R1_Extend
  562.     dec    ax
  563.     jz    $R1_Expand
  564.  
  565.     mov    si, 1                ; Read one block
  566.     call    $Read_XMS
  567.     jmp    $Read1_OK
  568.  
  569. $R1_Disk:
  570.     call    $Read_disk
  571.     jmp    $Read1_OK
  572.  
  573. $R1_Extend:
  574.     call    $Read_extend
  575.     jmp    $Read1_OK
  576.  
  577. $R1_Expand:
  578.     mov    si, word ptr cs:_SW_Blocks    ; Read first block
  579.     call    $Read_EMS
  580.  
  581. ;
  582. ; Complete - load error code and return
  583. ;
  584.  
  585. $Read1_OK:
  586.     pop    word ptr cs:_SW_intr        ; Restore interrupt flag
  587.     pop    ax
  588.  
  589. ;
  590. ; Exit function - Restore Control Interrupt handler
  591. ;
  592.  
  593. $SA_spawn_Exit:
  594.  
  595.     mov    di, word ptr cs:S_di        ; Restore saved registers
  596.     mov    si, word ptr cs:S_si
  597.     mov    ds, word ptr cs:S_ds
  598.  
  599.     mov    sp, bp
  600.     pop    bp
  601.     ret
  602.  
  603. SA_spawn1    endp
  604.  
  605. ;
  606. ; READ XMS DRIVER FUNCTION
  607. ;
  608. ;    BX - file handler
  609. ;    SI - Block count
  610. ;    DS - Output data segement
  611. ;
  612. $Read_XMS    proc    near
  613.     xor    ax, ax
  614.     mov    word ptr cs:XMS_SHandle, bx    ; Source - XMS
  615.     mov    word ptr cs:XMS_DHandle, ax    ; Dest - normal memory
  616.  
  617.     mov    word ptr cs:XMS_Soffset, ax    ; Source offset - zero
  618.     mov    word ptr cs:XMS_Soffset + 2, ax
  619.  
  620.     mov    word ptr cs:XMS_Doffset, ax    ; Dest offset DS:0
  621.     mov    ax, ds
  622.     mov    word ptr cs:XMS_Doffset + 2, ax
  623.  
  624.     cmp    si, 1                ; If first block, the
  625.     jz    $Read_X1            ; source offset is
  626.                         ; 4000H
  627.     mov    word ptr cs:XMS_Soffset, 04000H
  628.  
  629. ;
  630. ; Set up number of bytes: si * 16 * 1024
  631. ;
  632.  
  633. $Read_X1:
  634.     mov    ax, si
  635.     mov    dx, si
  636.     mov    cl, 14
  637.     shl    ax, cl
  638.     mov    cl, 2
  639.     shr    dx, cl
  640.     mov    word ptr cs:XMS_Length, ax    ; Load number of bytes
  641.     mov    word ptr cs:XMS_Length + 2, dx
  642.  
  643.     mov    ah, 0BH                ; Set up parameters
  644.     mov    dx, cs
  645.     mov    ds, dx
  646.     mov    si, offset XMS_DIF
  647.     call    cs:[_SW_XMS_Driver]
  648.     or    ax, ax
  649.     jnz     $Read_XMS1
  650.     jmp    Load_Error            ; XMS error - abort
  651.  
  652. $Read_XMS1:
  653.     ret
  654.  
  655. $Read_XMS    endp
  656.  
  657. ;
  658. ; READ DISK FUNCTION
  659. ;
  660. ;    BX - file handler
  661. ;    SI - Block count
  662. ;    DS - Output data segement
  663. ;
  664.  
  665. $Read_disk    proc    near
  666.  
  667.     mov    ax, 03f00H        ; Set up to read
  668.     mov    cx, 04000H        ; Load count
  669.     xor    dx, dx            ; Clear start address
  670.  
  671.     int    021H            ; Read the data
  672.  
  673.     jnc    $Read_OK        ; NO - abort
  674.     jmp    Load_Error        ; Abort - swap file error
  675.  
  676. ;
  677. ; Read OK - next block
  678. ;
  679.  
  680. $Read_OK:
  681.     dec    si            ; Decrement block count
  682.     mov    ax, ds            ; Increment offset
  683.     add    ax, 0400H
  684.     mov    ds, ax
  685.     ret
  686.  
  687. $Read_disk    endp
  688.  
  689. ;
  690. ; READ EMS FUNCTION
  691. ;
  692. ;    BX - file handler
  693. ;    SI - Block count - counts from max
  694. ;    DS - Output data segement
  695. ;
  696.  
  697. $Read_EMS    proc    near
  698.  
  699.     call    $map_ems_page        ; Map in the current EMS page
  700.     jnz    Load_Error
  701.  
  702.     push    ds            ; Save DS and SI
  703.     push    si
  704.     mov    ax, ds
  705.     mov    es, ax
  706.     mov    ds, word ptr cs:_SW_EMSFrame    ; Set Dest Seg
  707.     xor    si, si            ; Clear start
  708.     xor    di, di
  709.     mov    cx, 02000H        ; move 16K
  710.     pushf                ; Save direction flag
  711.     cld
  712.     rep movsw
  713.     popf                ; Restore direction flag
  714.     pop    si            ; And DS, SI
  715.     pop    ds
  716.     jmp    $Read_OK        ; Increment DS and dec SI
  717.  
  718. $Read_EMS    endp
  719.  
  720. ;
  721. ; MAP IN THE CURRENT EMS PAGE
  722. ;
  723. ;    BX - file handler
  724. ;    SI - Block count - counts from max
  725. ;    DS - Output data segement
  726. ;
  727.  
  728. $map_ems_page    proc    near
  729.  
  730.     push    bx            ; Need to save BX
  731.     mov    ax, 04400h        ; Map into physical page zero
  732.     mov    dx, bx            ; Set up handler
  733.     mov    bx, word ptr cs: _SW_Blocks
  734.     sub    bx, si
  735.  
  736.     int    067H
  737.     pop    bx
  738.  
  739.     or    ah, ah
  740.     ret
  741.  
  742. $map_ems_page    endp
  743.  
  744. ;
  745. ; DISK SEEK FUNCTION
  746. ;
  747. ;    BX - file handler
  748. ;    DX - offset
  749. ;
  750. $Seek_Disk    proc    near
  751.  
  752.     mov    ax, 04200H        ; Set seek
  753.     xor    cx, cx
  754.     int    021H
  755.     jc    Load_Error        ; Abort - swap file error
  756.     ret
  757.  
  758. $Seek_Disk    endp
  759.  
  760. ;
  761. ; PANIC - Abort
  762. ;
  763.  
  764. Load_Error    proc    near
  765.  
  766.     mov    di, offset Swap_PANIC
  767.     mov    bx, cs
  768.     mov    ds, bx
  769.  
  770. ;
  771. ;  Display message function
  772. ;
  773. ;  DS:DI message
  774. ;  AX is available
  775. ;
  776.  
  777.     mov    ah, 08H            ; Get foreground colour
  778.     xor    bx, bx
  779.     int    10H
  780.     mov    bl, ah
  781.     and    bl, 07h
  782.  
  783. ;
  784. ; Loop until a $ is hit, outputting the characters
  785. ;
  786. I24D:
  787.     mov    al, byte ptr ds:[di]
  788.     cmp    al, '$'
  789.     jz    $Wait_L
  790.  
  791.     push    di
  792.     mov    ah, 0EH
  793.     int    10H
  794.     pop    di
  795.     inc    di
  796.     jmp    I24D
  797.  
  798. $Wait_L:
  799.     sti
  800.     hlt
  801.     jmp    $Wait_L
  802.  
  803. Load_Error    endp
  804.  
  805. ;
  806. ;  WRITE EXTENDED MEMORY
  807. ;
  808. ;    SI - Block count
  809. ;
  810. $Write_extend    proc    near
  811.  
  812.     push    si            ; Save SI (block counter)
  813.     mov    cx, 02000H        ; Copy a 16K block
  814.     mov    ax, cs            ; Set up GDT address
  815.     mov    es, ax
  816.     mov    si, offset GD_table
  817.  
  818.     mov    ah, 087H        ; EMS function
  819.     int    015H
  820.     pop    si
  821.     ret
  822.  
  823. $Write_extend    endp
  824.  
  825. ;
  826. ;  READ FROM EXTENDED MEMORY
  827. ;
  828. ;    SI - Block count
  829. ;
  830.  
  831. $Read_extend    proc    near
  832.  
  833.     call    $Write_extend
  834.     jc    Load_Error        ; NO - abort
  835.  
  836.     dec    si            ; Decrement block count
  837.  
  838. $Read_extend    endp
  839.  
  840. ;
  841. ; INCREMENT Extended MEMORY GDT
  842. ;
  843. ;    AX - used
  844. ;
  845. $Inc_Extend    proc    near
  846.  
  847.     mov    ax, 04000H        ; Increment address by 16K
  848.     add    word ptr cs:GDT_dest_low, ax
  849.     adc    byte ptr cs:GDT_dest_high, 0
  850.     add    word ptr cs:GDT_src_low, ax
  851.     adc    byte ptr cs:GDT_src_high, 0
  852.     ret
  853.  
  854. $Inc_Extend    endp
  855.  
  856. ;
  857. ; LOAD SOURCE GDT ADDRESS
  858. ;
  859. ;    AX - low order
  860. ;    DL - high order
  861. ;
  862. $GDT_src_load    proc    near
  863.  
  864.  
  865.     mov    word ptr cs:GDT_src_low, ax
  866.     mov    byte ptr cs:GDT_src_high, dl
  867.     ret
  868.  
  869. $GDT_src_load    endp
  870.  
  871. ;
  872. ; LOAD DESTINATION GDT ADDRESS
  873. ;
  874. ;    AX - low order
  875. ;    DL - high order
  876. ;
  877. $GDT_dest_load    proc    near
  878.  
  879.     mov    word ptr cs:GDT_dest_low, ax
  880.     mov    byte ptr cs:GDT_dest_high, dl
  881.     ret
  882.  
  883. $GDT_dest_load    endp
  884.  
  885. ;
  886. ; LOAD the GDT for reloading
  887. ;
  888.  
  889. $GDT_reload    proc    near
  890.     mov    ax, word ptr cs:_SW_EMstart     ; Load Full start address
  891.     mov    dl, byte ptr cs:_SW_EMstart + 2
  892.     call    $GDT_src_load
  893.  
  894.     mov    ax, word ptr cs:SW_LMstart     ; Load Full start address
  895.     mov    dl, byte ptr cs:SW_LMstart + 2
  896.     call    $GDT_dest_load
  897.     ret
  898. $GDT_reload    endp
  899.  
  900. ;
  901. ; CONTROL C INTERRUPT HANDLER - IGNORE
  902. ;
  903.  
  904. _SW_Int23    proc    far
  905.     inc    word ptr cs:_SW_intr    ; Set Interrupt 23 detected.
  906.     cmp    byte ptr cs:_SW_I23_InShell, 0    ; are we in the shell?
  907.     jz    $SA_Ins
  908.  
  909. ; In another program - move the stack around
  910.  
  911.     stc
  912.     ret
  913.  
  914.  
  915. ; In shell - ignore interrupt 23 for the moment
  916.  
  917. $SA_Ins:
  918.     iret
  919.  
  920. _SW_Int23    endp
  921.  
  922. ;
  923. ; DIVIDE BY ZERO INTERRUPT HANDLER - Output message
  924. ;
  925.  
  926. _SW_Int00    proc    far
  927.  
  928.     mov    ax, 00900H
  929.     mov    dx, offset Swap_DZERO
  930.     mov    bx, cs
  931.     mov    ds, bx
  932.     int    021H
  933.  
  934.     mov    ax, 04CFFh        ; Exit
  935.     int    021H
  936.  
  937. _SW_Int00    endp
  938.  
  939. ;
  940. ;  Start of overwrite area for environment.  Align on a paragraph
  941. ;
  942. ;  Also the XMS driver functions used by SH3.C live here
  943. ;
  944.         ALIGN    16
  945. Env_OWrite:
  946.  
  947. ;
  948. ; XMS INTERFACE
  949. ;
  950. ; Get Version number.  Return the release number in AX
  951. ;
  952.  
  953. _SW_XMS_Gversion    proc    far
  954.  
  955.     push    bp            ; Save stack info
  956.     mov    bp, sp
  957.  
  958.     xor    ax, ax
  959.     call    cs:[_SW_XMS_Driver]
  960.  
  961.     mov    sp, bp
  962.     pop    bp
  963.     ret
  964.  
  965. _SW_XMS_Gversion    endp
  966.  
  967. ;
  968. ; Allocate N kbytes.  Return the Handler in AX or -1 and error code in
  969. ; errno.
  970. ;
  971. ; Size will be in bp + 6.
  972. ;
  973.  
  974. _SW_XMS_Allocate    proc    far
  975.  
  976.     push    bp            ; Save stack info
  977.     mov    bp, sp
  978.  
  979.     mov    dx, word ptr ss:[bp + 6]
  980.     mov    ah, 09H
  981.     call    cs:[_SW_XMS_Driver]
  982.     or    ax, ax
  983.     jnz    $SW_A1
  984.  
  985. ;
  986. ; Allocate Failed - return error code
  987. ;
  988.     xor    ax, ax
  989.     dec    ax
  990.     xor    bh, bh
  991.     mov    word ptr ds:_errno, bx    ; Save error code
  992.     jmp    $SW_A2
  993.  
  994. ;
  995. ; Allocate OK - return handler
  996. ;
  997.  
  998. $SW_A1:
  999.     mov    ax, dx
  1000.  
  1001. $SW_A2:
  1002.     mov    sp, bp
  1003.     pop    bp
  1004.     ret
  1005.  
  1006. _SW_XMS_Allocate    endp
  1007.  
  1008. ;
  1009. ; Release handler.  Return 0 or error code.
  1010. ;
  1011. ; Handler will be in bp + 6.
  1012. ;
  1013.  
  1014. _SW_XMS_Free         proc    far
  1015.  
  1016.     push    bp            ; Save stack info
  1017.     mov    bp, sp
  1018.  
  1019.     mov    dx, word ptr ss:[bp + 6]
  1020.     mov    ah, 0AH
  1021.     call    cs:[_SW_XMS_Driver]
  1022.     or    ax, ax
  1023.     jnz    $SW_F1
  1024. ;
  1025. ; Free Failed - return error code
  1026. ;
  1027.     mov    al, bl
  1028.     jmp    $SW_F2
  1029.  
  1030. ;
  1031. ; Free OK - return zero
  1032. ;
  1033. $SW_F1:
  1034.     xor    ax, ax
  1035.  
  1036. $SW_F2:
  1037.     mov    sp, bp
  1038.     pop    bp
  1039.     ret
  1040.  
  1041. _SW_XMS_Free         endp
  1042.  
  1043. ;
  1044. ; Get available memory space.  Return 0 if failed.
  1045. ;
  1046.  
  1047.  
  1048. _SW_XMS_Available    proc    far
  1049.  
  1050.     push    bp            ; Save stack info
  1051.     mov    bp, sp
  1052.     mov    ah, 08H
  1053.     call    cs:[_SW_XMS_Driver]
  1054.     or    bl, bl
  1055.     jz    $SW_Avail1
  1056.  
  1057. ;
  1058. ; Free Failed - return zero
  1059. ;
  1060.     xor    ax, ax
  1061.  
  1062. $SW_Avail1:
  1063.     mov    sp, bp
  1064.     pop    bp
  1065.     ret
  1066.  
  1067. _SW_XMS_Available    endp
  1068.  
  1069. ;
  1070. ; Main entry point
  1071. ;
  1072.  
  1073. _SA_spawn    proc    far
  1074.  
  1075.     push    bp
  1076.     mov    bp, sp
  1077.  
  1078. ;
  1079. ; Entry Offsets
  1080. ;
  1081. ;    Environment      = 6
  1082. ;
  1083.  
  1084.     mov    word ptr cs:S_di, di        ; Save registers
  1085.     mov    word ptr cs:S_si, si
  1086.     mov    word ptr cs:S_ds, ds
  1087.  
  1088. ;
  1089. ; Save the length of the current MCB block;
  1090. ;
  1091.  
  1092.     mov    ax, word ptr ds:__psp
  1093.     dec    ax
  1094.     mov    word ptr cs:N_mcb, ax        ; Save MCB address for swap out
  1095.  
  1096. ; Calculate low mem start for extended memory
  1097.  
  1098.     mov    bx, ax                ; Save copy
  1099.     mov    cl, 4                ; mult low order by 16
  1100.     shl    ax, cl
  1101.     mov    word ptr cs:SW_LMstart, ax    ; Save low order
  1102.     mov    cl, 12                ; div by 16 ** 3
  1103.     shr    bx, cl
  1104.     mov    byte ptr cs:SW_LMstart + 2, bl    ; Save low order
  1105.  
  1106. ;
  1107. ; Set up Environment segment in execute structure
  1108. ;
  1109.  
  1110.     mov    bx, cs
  1111.     mov    ax, offset Env_OWrite
  1112.     mov    cl, 4
  1113.     shr    ax, cl
  1114.     add    ax, bx
  1115.     mov    word ptr cs:exec_env, ax    ; Save Env seg.
  1116.  
  1117. ;
  1118. ; Set up rest of execute structure
  1119. ;
  1120.  
  1121.     mov    word ptr cs:exec_cseg, cs    ; Command line address
  1122.     mov    word ptr cs:exec_f1seg, cs    ; FCB 1 address
  1123.     mov    word ptr cs:exec_f2seg, cs    ; FCB 2 address
  1124.  
  1125. ;
  1126. ; Generate the FCBs
  1127. ;
  1128.  
  1129.     mov    ax, cs        ; Set up segments
  1130.     mov    ds, ax
  1131.     mov    es, ax
  1132.  
  1133.     mov    ax, 02901H    ; Set up FCB interrupt
  1134.     mov    si, offset _cmd_line + 1
  1135.     mov    di, offset FCB1    ; FCB 1;
  1136.  
  1137.     int    021H        ; Execute the interrupt
  1138.  
  1139.     mov    ax, cs        ; Set up segment
  1140.     mov    es, ax
  1141.  
  1142.     mov    ax, 02901H    ; Reset AX cause errors are ignored
  1143.     mov    di, offset FCB2    ; FCB 2;
  1144.  
  1145.     int    021H        ; Execute the interrupt
  1146.  
  1147. ;
  1148. ; Copy out to the swap file
  1149. ;
  1150.  
  1151.     mov    bx, word ptr cs:_SW_fp        ; Load file handler
  1152.     mov    si, word ptr cs:_SW_Blocks    ; Load Number of blocks to read
  1153.     mov    ax, word ptr cs:N_mcb        ; Load the start address
  1154.     push    ax
  1155.  
  1156. ; load up extended memory GDT for destination
  1157.  
  1158.     mov    ax, word ptr cs:_SW_EMstart
  1159.     mov    dl, byte ptr cs:_SW_EMstart + 2
  1160.     call    $GDT_dest_load
  1161.  
  1162. ;
  1163. ; set up DS register with start of start copy
  1164. ;
  1165.  
  1166.     pop    ax
  1167.     mov    ds, ax
  1168.     mov    ax, word ptr cs:SW_LMstart     ; Load Full start address
  1169.     mov    dl, byte ptr cs:SW_LMstart + 2
  1170.     call    $GDT_src_load
  1171.  
  1172. ;
  1173. ; Check for end of copy - BX contains the file handler for disk write
  1174. ;
  1175.  
  1176. $Write_loop:
  1177.     or    si, si
  1178.     jnz    $Write_L1
  1179.     jmp    $Write_Complete
  1180.  
  1181. ; OK - Copy next 0x4000 bytes - switch on device
  1182.  
  1183. $Write_L1:
  1184.     mov    ax, word ptr cs: _SW_Mode
  1185.     dec    ax
  1186.     jz    $W_disk
  1187.     dec    ax
  1188.     jnz    $Write_L2
  1189.     jmp    $W_extend
  1190. $Write_L2:
  1191.     dec    ax
  1192.     jnz    $W_xms
  1193.     jmp    $W_expand
  1194.  
  1195. ;
  1196. ; Write to XMS driver.  In this case, we do one write and let the driver
  1197. ; sort out the blocking
  1198. ;
  1199. $W_xms:
  1200.     xor    ax, ax
  1201.     mov    word ptr cs:XMS_SHandle, ax    ; Source - normal memory
  1202.     mov    word ptr cs:XMS_DHandle, bx    ; Dest - XMS
  1203.  
  1204.     mov    word ptr cs:XMS_Doffset, ax    ; Dest offset - zero
  1205.     mov    word ptr cs:XMS_Doffset + 2, ax
  1206.  
  1207.     mov    word ptr cs:XMS_Soffset, ax    ; Source offset DS:0
  1208.     mov    ax, ds
  1209.     mov    word ptr cs:XMS_Soffset + 2, ax
  1210.  
  1211. ;
  1212. ; Set up number of bytes SW_Block * 16 * 1024
  1213. ;
  1214.  
  1215.     mov    ax, si
  1216.     mov    dx, si
  1217.     mov    cl, 14
  1218.     shl    ax, cl
  1219.     mov    cl, 2
  1220.     shr    dx, cl
  1221.     mov    word ptr cs:XMS_Length, ax    ; Load number of bytes
  1222.     mov    word ptr cs:XMS_Length + 2, dx
  1223.  
  1224.     mov    ah, 0BH                ; Set up parameters
  1225.     mov    dx, cs
  1226.     mov    ds, dx
  1227.     mov    si, offset XMS_DIF
  1228.     call    cs:[_SW_XMS_Driver]
  1229.     or    ax, ax
  1230.     jnz     $Write_Complete
  1231.  
  1232. ; XMS error - abort
  1233.  
  1234.     mov    ah, bl
  1235.     jmp    $Write_error
  1236.  
  1237. ;
  1238. ; Write to disk
  1239. ;
  1240. $W_disk:
  1241.     call    $Write_disk
  1242.  
  1243. ; Increment counter
  1244.  
  1245. $Write_Incr:
  1246.     dec    si            ; Decrement block count
  1247.     mov    ax, ds            ; Increment offset
  1248.     add    ax, 0400H
  1249.     mov    ds, ax
  1250.     jmp    $Write_loop
  1251.  
  1252. ; Write to extended memory
  1253.  
  1254. $W_extend:
  1255.     call    $Write_extend
  1256.     jc    $Write_error        ; NO - abort
  1257.  
  1258.     dec    si            ; Decrement block count
  1259.     call    $Inc_Extend
  1260.     jmp    $Write_loop
  1261.  
  1262. ; Write to expanded memory
  1263. ;    BX - handler
  1264. ;    SI - count
  1265. ;    DS - source segment
  1266. ;
  1267. $W_expand:
  1268.     call    $map_ems_page        ; Map in the current EMS page
  1269.     jnz    $Write_error
  1270.  
  1271.     push    ds            ; Save DS and SI
  1272.     push    si
  1273.     mov    es, word ptr cs:_SW_EMSFrame    ; Set Dest Seg
  1274.     xor    si, si            ; Clear start
  1275.     xor    di, di
  1276.     mov    cx, 02000H        ; move 16K
  1277.     pushf                ; Save direction flag
  1278.     cld
  1279.     rep movsw
  1280.     popf                ; Restore direction flag
  1281.     pop    si            ; And DS, SI
  1282.     pop    ds
  1283.     jmp    $Write_Incr        ; Increment DS and dec SI
  1284.  
  1285. ;
  1286. ; Error - abort.  The error code is in AH.
  1287. ;
  1288.  
  1289. $Write_error:
  1290.     mov    ds, word ptr cs:S_ds    ; Restore DS
  1291.     mov    al, ah
  1292.     xor    ah, ah
  1293.     mov    word ptr ds:_errno, ax    ; Save error code
  1294.  
  1295. $Write_Error1:
  1296.     mov    ax, 0FFFEH
  1297.     jmp    $SA_spawn_Exit        ; Exit
  1298.  
  1299. ;
  1300. ; Swap file is now written, set up environment.  If this was a partial
  1301. ; write, we need to write the first 4K.
  1302. ;
  1303.  
  1304. $Write_Complete:
  1305.         jmp    SA_spawn1
  1306. _SA_spawn    endp
  1307.  
  1308. ;
  1309. ; WRITE DISK FUNCTION
  1310. ;
  1311. ;    BX - file handler
  1312. ;    SI - Block count
  1313. ;    DS - Output data segement
  1314. ;
  1315.  
  1316. $Write_disk    proc    near
  1317.  
  1318.     mov    ax, 04000H        ; Set up to write
  1319.     mov    cx, ax            ; Load count
  1320.     xor    dx, dx            ; Clear start address
  1321.     push    bx            ; Save FP
  1322.     push    si            ; Save count and Data Segment
  1323.  
  1324.     int    021H            ; Write the data
  1325.  
  1326.     pop    si            ; Restore Regs
  1327.     pop    bx
  1328.     jnc    $Write_disk1        ; NO error - continue
  1329.  
  1330. ;
  1331. ; Error - abort
  1332. ;
  1333.     mov    ds, word ptr cs:S_ds    ; Restore DS
  1334.     mov    ah, al
  1335.     call    far ptr __maperror    ; Map the error
  1336.     jmp    $Write_Error1
  1337.  
  1338. ; Check for 16K write
  1339.  
  1340. $Write_disk1:
  1341.     cmp    ax, 04000H
  1342.     jnz    $Write_disk2
  1343.     ret
  1344.  
  1345. $Write_disk2:
  1346.     mov    ax,01c1cH        ; Set disk full
  1347.     jmp    $Write_error        ; NO - abort
  1348.  
  1349. $Write_disk    endp
  1350.  
  1351. ;
  1352. ; END OF SWAPPER
  1353. ;
  1354. SWAP_TEXT    ends
  1355.         end
  1356.